/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.icee.myth.server.card;

import com.icee.myth.config.MapConfig;
import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.GameLogMessage.GameLogType;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.protobuf.ExternalCommonProtocol.CardProto;
import com.icee.myth.protobuf.ExternalCommonProtocol.CardsProto;
import com.icee.myth.protobuf.ExternalCommonProtocol.IntValuesProto;
import com.icee.myth.protobuf.builder.ClientToMapBuilder;
import com.icee.myth.server.GameServer;
import com.icee.myth.server.activity.cardDrawActivity.CardDrawActivityTemplate;
import com.icee.myth.server.activity.cardDrawActivity.CardDrawActivityTemplates;
import com.icee.myth.server.actor.Human;
import com.icee.myth.server.card.cardDraw.CardDrawItem;
import com.icee.myth.server.card.cardDraw.CardDrawStaticInfo;
import com.icee.myth.server.card.cardDraw.CardDrawsConfig;
import com.icee.myth.server.levelup.CardLevelsConfig;
import com.icee.myth.server.levelup.HumanLevelsConfig;
import com.icee.myth.utils.Consts;
import com.icee.myth.utils.IdValue;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * 卡片管理器
 * @author liuxianke
 */
public class Cards {

    public final Human human;
    public final TreeMap<Integer, Card> cards = new TreeMap<Integer, Card>();
    public int nextCardInstId;

    public Cards(Human human, CardsProto cardsProto) {
        this.human = human;

        if (cardsProto != null) {
            List<CardProto> cardProtos = cardsProto.getCardsList();
            for (CardProto cardProto : cardProtos) {
                cards.put(cardProto.getInstId(), CardFactories.INSTANCE.getCardFactory(cardProto.getId()).buildCard(human, cardProto.getInstId(), cardProto.getLevel(), cardProto.getExperience()));
            }

            this.nextCardInstId = cardsProto.getNextCardInstId();
        } else {
            this.nextCardInstId = 1;
        }
    }

    public CardsProto buildCardsProto() {
        CardsProto.Builder builder1 = CardsProto.newBuilder();

        builder1.setNextCardInstId(nextCardInstId);

        for (Card card : cards.values()) {
            builder1.addCards(card.buildCardProto());
        }

        return builder1.build();
    }

    public Card addCard(CardFactory cardFactory, int level, int experience, boolean needSend) {
        Card card = cardFactory.buildCard(human, nextCardInstId, level, experience);
        cards.put(nextCardInstId, card);
        nextCardInstId++;

        if (needSend) {
            // 通知玩家添加新卡片
            human.sendMessage(ClientToMapBuilder.buildCardAdd(nextCardInstId - 1, cardFactory.staticInfo.id, level));
        }

        return card;
    }

    public Card addCard(int id, int level, int experience, boolean needSend) {
        CardFactory cardFactory = CardFactories.INSTANCE.getCardFactory(id);
        if (cardFactory != null) {
            return addCard(cardFactory, level, experience, needSend);
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] add card[" + id + "] error because card not found."));
        }

        return null;
    }

    public boolean removeCard(int instId, boolean needSend) {
        Card card = cards.get(instId);
        if (card != null) {
            if (card.place == Consts.PLACE_TYPE_NONE) {
                return removeCard1(instId, needSend);
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] remove card[" + instId + "] error because card in place[" + card.place + "]."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] remove card[" + instId + "] error because card not found."));
        }

        return false;
    }

    /**
     * 内部删除卡方法，不判断是否在阵型中（阵中判断在调用方法外面进行）
     * @param instId
     * @param needSend
     * @return
     */
    private boolean removeCard1(int instId, boolean needSend) {
        if (cards.remove(instId) != null) {
            if (needSend) {
                // 通知玩家失去卡片
                human.sendMessage(ClientToMapBuilder.buildCardRemove(instId));
            }

            return true;
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] remove card[" + instId + "] error because card not found."));
        }

        return false;
    }

    public Card getCard(int instId) {
        return cards.get(instId);
    }

    /**
     * 用食物卡片foods强化instId号卡片
     * @param instId    要强化的卡片实例id
     * @param foods     用来强化的食物卡片
     */
    public void strengthen(int instId, List<Integer> foods, boolean needSend) {
        Card card = cards.get(instId);
        if (card != null) {
            if (card.level < card.staticInfo.maxLv) {
                if (!foods.isEmpty()) {
                    if (foods.size() <= Consts.MAX_FOODCARD_NUM) {
                        // 确认食物卡片存在且不在阵型中
                        int needSilver = 0;
                        int totalEatExp = 0;
                        for (int foodId : foods) {
                            if (foodId != instId) {
                                Card foodCard = cards.get(foodId);
                                if (foodCard == null) {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + human.id + "] strengthen card[" + instId + "] error because food card[" + foodId + "] not exist."));
                                    return;
                                } else if (foodCard.place != Consts.PLACE_TYPE_NONE) {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + human.id + "] strengthen card[" + instId + "] error because food card[" + foodId + "] in place[" + foodCard.place + "]."));
                                    return;
                                }

                                // 计算花费
                                needSilver += (foodCard.staticInfo.star1 * (foodCard.staticInfo.star1 + 1) + foodCard.staticInfo.star2) / 2 * MapConfig.INSTANCE.strengthenCardPriceRatio;

                                // 计算食物卡片经验总数
                                totalEatExp += (CardLevelsConfig.INSTANCE.levelConfigs[foodCard.level - 1].totalExperience + foodCard.experience) * MapConfig.INSTANCE.eatCardExperienceRatio;
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] strengthen card[" + instId + "] error because try to eat itself."));
                                return;
                            }
                        }

                        if (human.getSilver() >= needSilver) {
                            human.decreaseSilver(needSilver, Consts.SOUL_CHANGE_LOG_TYPE_STRENGTHEN_CARD, instId, needSend);

                            int[] ids = new int[Consts.MAX_FOODCARD_NUM];       // 用于记录行为日志
                            int i = 0;                                          // 用于记录行为日志
                            for (int foodId : foods) {
                                removeCard1(foodId, needSend);

                                ids[i] = foodId;                                // 用于记录行为日志
                                i++;                                            // 用于记录行为日志
                            }
                            card.increaseExperience(totalEatExp, needSend);

                            // 记录行为日志
                            if (MapConfig.INSTANCE.useCYLog == true) {
                                List<String> cyLogList = new ArrayList<String>();
                                cyLogList.add("evolutionMC");
                                cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                                cyLogList.add("KDTY");
                                cyLogList.add(String.valueOf(human.id));
                                cyLogList.add(human.name);
                                cyLogList.add("");
                                cyLogList.add(String.valueOf(human.lv));
                                cyLogList.add(String.valueOf(instId));
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_EVOLUTION));

                                cyLogList = new ArrayList<String>();
                                cyLogList.add("behaviorMC");
                                cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                                cyLogList.add("KDTY");
                                cyLogList.add(String.valueOf(human.id));
                                cyLogList.add(human.name);
                                cyLogList.add("");
                                cyLogList.add("StrengthenCardDBBehavior");
                                cyLogList.add(instId + " " + ids[0] + " " + ids[1] + " " + ids[2] + " " + ids[3] + " " + ids[4] + " " + ids[5] + " " + ids[6] + " " + ids[7]);
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_BEHAVIOR));
                            }

                            GameLogger.getlogger().log(GameLogMessageBuilder.buildStrengthenCardDBBehaviorGameLogMessage(human.id, instId, ids[0], ids[1], ids[2], ids[3], ids[4], ids[5], ids[6], ids[7], totalEatExp));
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] strengthen card[" + instId + "] error because no enough silver[" + needSilver + "]."));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + human.id + "] strengthen card[" + instId + "] error because too many food cards."));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] strengthen card[" + instId + "] error because no food."));
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] strengthen card[" + instId + "] error because level limit."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] strengthen card[" + instId + "] error because card not found."));
        }
    }

    /**
     * 转生
     * @param instId    要转生的卡
     * @param foodIds   材料卡
     * @param needSend
     */
    public void transform(int instId, List<Integer> foodIds, boolean needSend) {
        Card card = cards.get(instId);
        if (card != null) {
            if (card.level >= card.staticInfo.maxLv) {
                CardTransformInfo transformInfo = card.staticInfo.transformInfo;

                // 若卡片在阵型上，需要判断是否转生会使领导力越界(转生会使卡片领导力加1)
                if ((card.place != Consts.PLACE_TYPE_SANDBOX) || (human.sandbox.getTotalLeaderPoint() < HumanLevelsConfig.INSTANCE.levelConfigs[human.lv - 1].leaderPoint)) {
                    if (transformInfo != null) {
                        // 校验所需卡片
                        if ((transformInfo.needCards != null) && (transformInfo.needCards.length > 0)) {
                            if (foodIds != null) {
                                int foodCardNum = foodIds.size();
                                int totalCardNum = 0;
                                // 收集食物卡片
                                TreeSet<Card> foodCards = new TreeSet();
                                int i = 0;
                                for (int foodId : foodIds) {
                                    if (foodId != instId) {
                                        Card foodCard = cards.get(foodId);

                                        if (foodCard == null) {
                                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                    "Player[" + human.id + "] transform card[" + instId + "] error because food card[" + foodId + "] not found."));
                                            return;
                                        }

                                        // 防止玩家复制卡片
                                        if (!foodCards.add(foodCard)) {
                                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                    "Player[" + human.id + "] transform card[" + instId + "] error because food card[" + foodId + "] duplicated."));
                                            return;
                                        }

                                        // 确认食物卡片不在阵型中
                                        if (foodCard.place != Consts.PLACE_TYPE_NONE) {
                                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                    "Player[" + human.id + "] transform card[" + instId + "] error because food card[" + foodId + "] in place[" + foodCard.place + "]."));
                                            return;
                                        }

                                        i++;
                                    } else {
                                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                "Player[" + human.id + "] transform card[" + instId + "] error because try to eat itself."));
                                        return;
                                    }
                                }

                                // 校验食物卡
                                for (IdValue idValue : transformInfo.needCards) {
                                    totalCardNum += idValue.value;
                                    int remainNum = idValue.value;
                                    for (Card foodCard : foodCards) {
                                        if (foodCard.staticInfo.id == idValue.id) {
                                            remainNum--;

                                            if (remainNum == 0) {
                                                break;
                                            }
                                        }
                                    }

                                    if (remainNum > 0) {
                                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                                "Player[" + human.id + "] transform card[" + instId + "] error because not enough food[" + idValue.id + "]."));
                                        return;
                                    }
                                }

                                if (totalCardNum != foodCardNum) {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + human.id + "] transform card[" + instId + "] error because too many food cards."));
                                    return;
                                }
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] transform card[" + instId + "] error because no food cards."));
                                return;
                            }
                        }

                        // 判断所需物品是否满足
                        if ((transformInfo.needItems != null) && (transformInfo.needItems.length > 0)) {
                            for (IdValue idValue : transformInfo.needItems) {
                            	int valueId = idValue.id;
                            	//FIXME 处理item id
//                            	if(valueId >= 10000) {
//                            		valueId -= 9000;
//                            	}
                                if (human.items.getItemNum(valueId) < idValue.value) {
                                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                            "Player[" + human.id + "] transform card[" + instId + "] error because not enough item[" + idValue.id + "]."));
                                    return;
                                }
                            }
                        }

                        CardFactory cardFactory = CardFactories.INSTANCE.getCardFactory(transformInfo.targetId);
                        if (cardFactory != null) {
                            int[] ids = new int[Consts.MAX_FOODCARD_NUM];           // 用于记录行为日志
                            int i = 0;                                              // 用于记录行为日志
                            // 消耗食物卡片
                            if (foodIds != null) {
                                for (int foodId : foodIds) {
                                    removeCard1(foodId, needSend);

                                    ids[i] = foodId;                                // 用于记录行为日志
                                    i++;                                            // 用于记录行为日志
                                }
                            }

                            // 消耗物品
                            if ((transformInfo.needItems != null) && (transformInfo.needItems.length > 0)) {
                                human.items.consumeItems(transformInfo.needItems, needSend);
                            }

                            // 变身
                            card.staticInfo = cardFactory.staticInfo;

                            // 若卡片是队长卡，修改全局玩家简略信息
                            if (human.sandbox.slots[human.sandbox.leader].id == card.id) {
                                GameServer.INSTANCE.briefPlayerInfos.setPlayerLeaderCard(human.id, card.staticInfo.id, card.level);

                                // 通知朋友队长信息改变
                                human.broadcastToFriends(ClientToMapBuilder.buildFriendLeaderCardChange(human.id, card.staticInfo.id, card.level));
                            }

                            // 通知客户端变身
                            if (needSend) {
                                human.sendMessage(ClientToMapBuilder.buildCardTransform(card.id, card.staticInfo.id));
                            }
                            
                            // 记录行为日志
                            if (MapConfig.INSTANCE.useCYLog == true) {
                                List<String> cyLogList = new ArrayList<String>();
                                cyLogList.add("evolutionMC");
                                cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                                cyLogList.add("KDTY");
                                cyLogList.add(String.valueOf(human.id));
                                cyLogList.add(human.name);
                                cyLogList.add("");
                                cyLogList.add(String.valueOf(human.lv));
                                cyLogList.add(String.valueOf(instId));
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_EVOLUTION));

                                cyLogList = new ArrayList<String>();
                                cyLogList.add("behaviorMC");
                                cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                                cyLogList.add("KDTY");
                                cyLogList.add(String.valueOf(human.id));
                                cyLogList.add(human.name);
                                cyLogList.add("");
                                cyLogList.add("TransformCardDBBehavior");
                                cyLogList.add(instId + " " + ids[0] + " " + ids[1] + " " + ids[2] + " " + ids[3] + " " + ids[4] + " " + ids[5] + " " + ids[6] + " " + ids[7]);
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_BEHAVIOR));
                            }


                            GameLogger.getlogger().log(GameLogMessageBuilder.buildTransformCardDBBehaviorGameLogMessage(human.id, instId, ids[0], ids[1], ids[2], ids[3], ids[4], ids[5], ids[6], ids[7], card.staticInfo.id));
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] transform card[" + instId + "] error because transform target card error."));
                        }
                    } else {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + human.id + "] transform card[" + instId + "] error because no transform target info."));
                    }
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] transform card[" + instId + "] error because leader point limit."));
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] transform card[" + instId + "] error because level limit."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] transform card[" + instId + "] error because card not found."));
        }
    }

    public void sold(IntValuesProto intValuesProto) {
        List<Integer> cardInstIds = intValuesProto.getValuesList();
        for (int cardInstId : cardInstIds) {
            Card card = cards.get(cardInstId);
            if (card != null) {
                // 确认卡片存在且不在阵型中
                if (card.place == Consts.PLACE_TYPE_NONE) {
                    removeCard1(cardInstId, true);

                    int soldPrice = card.staticInfo.soldPriceBase + card.staticInfo.soldPriceGrow * card.level;
                    human.increaseSilver(card.staticInfo.soldPriceBase + card.staticInfo.soldPriceGrow * card.level, Consts.SOUL_CHANGE_LOG_TYPE_SOLD_CARD, cardInstId, true);

                    // 记录行为日志
                    if (MapConfig.INSTANCE.useCYLog == true) {
                        List<String> cyLogList = new ArrayList<String>();
                        cyLogList.add("behaviorMC");
                        cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                        cyLogList.add("KDTY");
                        cyLogList.add(String.valueOf(human.id));
                        cyLogList.add(human.name);
                        cyLogList.add("");
                        cyLogList.add(String.valueOf(cardInstId));
                        cyLogList.add("");
                        cyLogList.add("");
                        cyLogList.add("");
                        cyLogList.add("");
                        cyLogList.add("");
                        cyLogList.add("");
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_BEHAVIOR));

                        cyLogList = new ArrayList<String>();
                                cyLogList.add("behaviorMC");
                                cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                                cyLogList.add("KDTY");
                                cyLogList.add(String.valueOf(human.id));
                                cyLogList.add(human.name);
                                cyLogList.add("");
                                cyLogList.add("SoldCardDBBehavior");
                                cyLogList.add(cardInstId + " " + soldPrice);
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                cyLogList.add("");
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_BEHAVIOR));
                    }
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildSoldCardDBBehaviorGameLogMessage(human.id, cardInstId, soldPrice));
                } else {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "Player[" + human.id + "] can't sold card[" + cardInstId + "] in sandbox."));
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] sold card[" + cardInstId + "] error because card not found."));
            }
        }
    }

    /**
     * 抽卡
     * @param drawId 卡包号
     * @param drawType 抽卡类型
     */
    public void draw(int drawId, int drawType, boolean drawAddiction) {
        CardDrawStaticInfo cardDrawStaticInfo = CardDrawsConfig.INSTANCE.getCardDrawStaticInfo(drawId);
        if (cardDrawStaticInfo != null) {
            if (human.vip.level >= cardDrawStaticInfo.vip) {
                switch (drawType) {
                    case Consts.CARD_DRAW_TYPE_SILVER_ONE_DRAW: {
                        if (cardDrawStaticInfo.silverOneDraw > 0) {
                            CardDrawActivityTemplate cardDrawActivityTemplate = CardDrawActivityTemplates.INSTANCE.getCardDrawActivityTemplate(drawId);
                            float discount = (cardDrawActivityTemplate != null) ? cardDrawActivityTemplate.getDiscount() : 1.0f;
                            int needSilver = (int) (cardDrawStaticInfo.silverOneDraw * discount);
                            if (human.getSilver() >= needSilver) {
                                human.decreaseSilver(needSilver, Consts.SOUL_CHANGE_LOG_TYPE_DRAW_CARD, drawId, true);
                                oneDraw(cardDrawStaticInfo, drawType, drawAddiction);
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] because no enough silver."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] ."));
                        }

                        break;
                    }
                    case Consts.CARD_DRAW_TYPE_GOLD_ONE_DRAW: {
                        if (cardDrawStaticInfo.goldOneDraw > 0) {
                            CardDrawActivityTemplate cardDrawActivityTemplate = CardDrawActivityTemplates.INSTANCE.getCardDrawActivityTemplate(drawId);
                            float discount = (cardDrawActivityTemplate != null) ? cardDrawActivityTemplate.getDiscount() : 1.0f;
                            int needGold = (int) (cardDrawStaticInfo.goldOneDraw * discount);
                            if (human.getGold() >= needGold) {
                                human.decreaseGold(needGold, Consts.SOUL_CHANGE_LOG_TYPE_DRAW_CARD, drawId, true, true);
                                oneDraw(cardDrawStaticInfo, drawType, drawAddiction);
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] because no enough gold."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] ."));
                        }

                        break;
                    }
                    case Consts.CARD_DRAW_TYPE_SILVER_SIX_DRAW: {
                        if (cardDrawStaticInfo.silverSixDraw > 0) {
                            CardDrawActivityTemplate cardDrawActivityTemplate = CardDrawActivityTemplates.INSTANCE.getCardDrawActivityTemplate(drawId);
                            float discount = (cardDrawActivityTemplate != null) ? cardDrawActivityTemplate.getDiscount() : 1.0f;
                            int needSilver = (int) (cardDrawStaticInfo.silverSixDraw * discount);
                            if (human.getSilver() >= needSilver) {
                                human.decreaseSilver(needSilver, Consts.SOUL_CHANGE_LOG_TYPE_DRAW_CARD, drawId, true);
                                sixDraw(cardDrawStaticInfo, drawType);
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] because no enough silver."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] ."));
                        }

                        break;
                    }
                    case Consts.CARD_DRAW_TYPE_GOLD_SIX_DRAW: {
                        if (cardDrawStaticInfo.goldSixDraw > 0) {
                            CardDrawActivityTemplate cardDrawActivityTemplate = CardDrawActivityTemplates.INSTANCE.getCardDrawActivityTemplate(drawId);
                            float discount = (cardDrawActivityTemplate != null) ? cardDrawActivityTemplate.getDiscount() : 1.0f;
                            int needGold = (int) (cardDrawStaticInfo.goldSixDraw * discount);
                            if (human.getGold() >= needGold) {
                                human.decreaseGold(needGold, Consts.SOUL_CHANGE_LOG_TYPE_DRAW_CARD, drawId, true, true);
                                sixDraw(cardDrawStaticInfo, drawType);
                            } else {
                                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                        "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] because no enough silver."));
                            }
                        } else {
                            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                    "Player[" + human.id + "] can't card draw[" + drawId + "] using type[" + drawType + "] ."));
                        }

                        break;
                    }
                    default: {
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                                FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                                "Player[" + human.id + "] card draw[" + drawId + "] error because unknown type[" + drawType + "]."));
                        break;
                    }
                }
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] card draw[" + drawId + "] error because vip limit."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] card draw[" + drawId + "] error because draw not found."));
        }
    }

    /**
     * 抽一张卡
     * @param cardDrawStaticInfo
     * @param drawType
     * @param drawAddiction
     */
    private void oneDraw(CardDrawStaticInfo cardDrawStaticInfo, int drawType, boolean drawAddiction) {
        CardDrawItem cardDrawItem = (drawAddiction && (cardDrawStaticInfo.addictions != null)) ? cardDrawStaticInfo.drawAddiction() : cardDrawStaticInfo.draw();

        Card card = addCard(cardDrawItem.cardId, cardDrawItem.level, 0, true);
        if (card != null) {
            // 返回客户端所抽到的卡(做表现用)
            human.sendMessage(ClientToMapBuilder.buildCardDrawed(cardDrawItem));

            // 记录行为日志
            if (MapConfig.INSTANCE.useCYLog == true) {
                List<String> cyLogList = new ArrayList<String>();
                cyLogList.add("behaviorMC");
                cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                cyLogList.add("KDTY");
                cyLogList.add(String.valueOf(human.id));
                cyLogList.add(human.name);
                cyLogList.add("");
                cyLogList.add("DrawCardDBBehavior");
                cyLogList.add(drawType + " " + card.id + " " + 0 + " " + 0 + " " + 0 + " " + 0 + " " + 0);
                cyLogList.add("");
                cyLogList.add("");
                cyLogList.add("");
                cyLogList.add("");
                cyLogList.add("");
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_BEHAVIOR));
            }
            GameLogger.getlogger().log(GameLogMessageBuilder.buildDrawCardDBBehaviorGameLogMessage(human.id, drawType, card.id, 0, 0, 0, 0, 0));
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] draw card[" + cardDrawItem.cardId + "] error because card not found."));
        }
    }

    private void sixDraw(CardDrawStaticInfo cardDrawStaticInfo, int drawType) {
        ArrayList<CardDrawItem> cardDrawItems = new ArrayList<CardDrawItem>(6);
        boolean hasGoodCard = false;
        Card[] cardInstIds = new Card[6];
        for (int i = 0; i < 6; i++) {
            CardDrawItem cardDrawItem = cardDrawStaticInfo.draw();
            CardFactory cardFactory = CardFactories.INSTANCE.getCardFactory(cardDrawItem.cardId);
            if (cardFactory != null) {
                hasGoodCard |= cardFactory.staticInfo.star1 >= 5;   // 是否有好卡判断（紫卡）
                if ((i == 5) && !hasGoodCard && (cardDrawStaticInfo.addictions != null)) {
                    // 从补充卡包中抽出一张替换
                    cardDrawItem = cardDrawStaticInfo.drawAddiction();
                    cardFactory = CardFactories.INSTANCE.getCardFactory(cardDrawItem.cardId);
                }
            }

            if (cardFactory != null) {
                cardInstIds[i] = addCard(cardFactory, cardDrawItem.level, 0, true);
                cardDrawItems.add(cardDrawItem);
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] draw card[" + cardDrawItem.cardId + "] error because card not found."));
            }
        }

        // 记录行为日志
        if (MapConfig.INSTANCE.useCYLog == true) {
            List<String> cyLogList = new ArrayList<String>();
            cyLogList.add("behaviorMC");
            cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
            cyLogList.add("KDTY");
            cyLogList.add(String.valueOf(human.id));
            cyLogList.add(human.name);
            cyLogList.add("");
            cyLogList.add("DrawCardDBBehavior");
            cyLogList.add(drawType + " " + cardInstIds[0].id + " " + cardInstIds[1].id + " " + cardInstIds[2].id + " " + cardInstIds[3].id + " " + cardInstIds[4].id + " " + cardInstIds[5].id);
            cyLogList.add("");
            cyLogList.add("");
            cyLogList.add("");
            cyLogList.add("");
            cyLogList.add("");
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogType.GAMELOGTYPE_CY_BEHAVIOR));
        }
        GameLogger.getlogger().log(GameLogMessageBuilder.buildDrawCardDBBehaviorGameLogMessage(human.id, drawType, cardInstIds[0].id, cardInstIds[1].id, cardInstIds[2].id, cardInstIds[3].id, cardInstIds[4].id, cardInstIds[5].id));

        // 返回客户端所抽到的卡(做表现用)
        human.sendMessage(ClientToMapBuilder.buildCardDrawed(cardDrawItems));
    }
    
}
